// Dynamic reading of config files with boost::program_options
// to compile: g++ -I/opt/local/include /opt/local/lib/libboost_program_options.a read-config-file.cpp


#include <iostream>
#include <fstream>
#include <sstream>
#include <boost/program_options.hpp>

namespace po = boost::program_options;

int main()
{
  po::options_description config;
  po::variables_map vm;

  std::string filename = "po.cfg";

  std::ifstream ifs(filename.c_str());
  if (!ifs)
    {
      std::cout << "File po.cfg not found!" << std::endl;
    }

  std::size_t n;

  // First, we just read the number of people N
  config.add_options()
    ("N", po::value<std::size_t>(&n)->default_value(2), "Number of people");

  po::store(po::parse_config_file(ifs, config, true), vm);
  po::notify(vm);

  std::cout << "Number of people = " << n << std::endl;

  // Need to close and reopen the file for a fresh read
  ifs.close();
  ifs.open(filename.c_str());

  std::vector<std::string> str_sigs(n);
  std::stringstream out;
  std::string signature_location;

  // Dynamically add options for people's name
  // depending on the number of people which is now known
  for (std::size_t i = 1; i <= n; ++i)
    {
      // Convert an integer to string
      out.str("");
      out << i;
      signature_location = "Name.Person" + out.str();

      config.add_options()
	(signature_location.c_str(), po::value<std::string>(&str_sigs[i-1]), "Names");
    }

  // Now read the file again
  po::store(po::parse_config_file(ifs, config, true), vm);
  po::notify(vm);

  std::cout << "Names from config file:" << std::endl;
  for (std::vector<std::string>::const_iterator it = str_sigs.begin(); 
       it != str_sigs.end(); ++it)
    {
      std::cout << "  " << *it << std::endl;
    }
}

// Local Variables:
// mode: C++
// End:
